package com.cloud.sample.provider;

import com.cloud.common.exception.AppException;
import com.cloud.common.util.UUIDUtils;
import com.cloud.sample.util.FileHelper;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

@Slf4j
@Component
public class MinioProvider {
    /**
     * minio访问地址
     */
    @Value("${minio.endpoint}")
    private String endpoint;

    /**
     * minio访问账号
     */
    @Value("${minio.accessKey}")
    private String accessKey;

    /**
     * minio访问密码
     */
    @Value("${minio.secretKey}")
    private String secretKey;

    /**
     * 文件桶的名称
     */
    @Value("${minio.bucket}")
    private String bucket;

    /**
     * minio访问入口地址
     */
    @Value("${minio.url}")
    private String url;

    private MinioClient minioClient;

    @PostConstruct
    public void init() {
        minioClient = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
    }

    public String getFileUrl(String fileName) {
        return url + "/" + bucket + "/" + fileName;
    }

    public String uploadFile(MultipartFile file, boolean noCompress) throws Exception {
        String originalFilename = file.getOriginalFilename();
        if (!originalFilename.contains(".")) {
            throw new AppException("文件名必须包含扩展名");
        }
        String uploadFileName;
        String contentType = getContentType(originalFilename);
        if (noCompress || !isImage(contentType)) {
            uploadFileName = FileHelper.getRandomFileName(originalFilename);
            doUpload(uploadFileName, file.getInputStream(), file.getSize());
        } else {
            // 压缩保存到临时文件，压缩格式为jpg
            uploadFileName = UUIDUtils.get() + ".jpg";
            String targetFilePath = System.getProperty("java.io.tmpdir") + uploadFileName;
            Thumbnails.of(file.getInputStream()).scale(1).outputQuality(0.6).toFile(targetFilePath);
            FileInputStream inputStream = new FileInputStream(targetFilePath);
            try {
                doUpload(uploadFileName, inputStream, inputStream.available());
            } finally {
                inputStream.close();
                FileUtils.forceDelete(new File(targetFilePath));
            }
        }
        log.info("uploadFile fileName={}", uploadFileName);
        return uploadFileName;
    }

    public InputStream downloadFile(String fileName) throws Exception {
        DownloadObjectArgs objectArgs = DownloadObjectArgs.builder()
                .bucket(bucket)
                .object(fileName)
                .build();
        return minioClient.getObject(new GetObjectArgs(objectArgs));
    }

    public void deleteFile(String fileName) throws Exception {
        RemoveObjectArgs objectArgs = RemoveObjectArgs.builder()
                .bucket(bucket)
                .object(fileName)
                .build();
        minioClient.removeObject(objectArgs);
        log.info("deleteFile fileName={}", fileName);
    }

    private void doUpload(String fileName, InputStream inputStream, long fileSize) throws Exception {
        PutObjectArgs objectArgs = PutObjectArgs.builder()
                .stream(inputStream, fileSize, -1)
                .contentType(getContentType(fileName))
                .bucket(bucket)
                .object(fileName)
                .build();
        minioClient.putObject(objectArgs);
    }

    private String getContentType(String fileName) {
        if (fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")) {
            return MediaType.IMAGE_JPEG_VALUE;
        }
        if (fileName.endsWith(".png")) {
            return MediaType.IMAGE_PNG_VALUE;
        }
        if (fileName.endsWith(".gif")) {
            return MediaType.IMAGE_GIF_VALUE;
        }
        if (fileName.endsWith(".html")) {
            return MediaType.TEXT_HTML_VALUE;
        }
        if (fileName.endsWith(".txt")) {
            return MediaType.TEXT_PLAIN_VALUE;
        }
        if (fileName.endsWith(".xml")) {
            return MediaType.TEXT_XML_VALUE;
        }
        return MediaType.APPLICATION_OCTET_STREAM_VALUE;
    }

    private boolean isImage(String contentType) {
        if (MediaType.IMAGE_JPEG_VALUE.equals(contentType)
                || MediaType.IMAGE_PNG_VALUE.equals(contentType)
                || MediaType.IMAGE_GIF_VALUE.equals(contentType)) {
            return true;
        }
        return false;
    }
}
